#include "cliente-m.h"
#define max_digitos_cta 4 /*indica la máxima cantidad de digitos en un nro de cuenta */
#define max_digitos_monto 12
#define tam_msj 25

char * obtener_servidor(){
	char * servidor;
	FILE * fp;
	fp = fopen("cliente.conf","r");
		if (fp == NULL)
		{
			printf("no se pudo obtener los datos del servidor");
			exit(1);
		}

	if (flock(fileno(fp), LOCK_SH) != 0 ){
		printf("no se pudo obtener el lock del archivo");
		exit(1);
	}
	servidor = leer_linea(fp, 1);

	fclose(fp);
	flock(fileno(fp), LOCK_UN);

	return servidor;
}

int obtener_puerto(){
	int puerto;
	FILE * fp;
	fp = fopen("cliente.conf","r");

	if (fp == NULL)
	{
		printf("no se pudo obtener los datos del servidor");
		exit(1);
	}

	if (flock(fileno(fp), LOCK_SH) != 0 )
	{
		printf("no se pudo obtener el lock del archivo");
		exit(1);
	}

	puerto = atoi(leer_linea(fp, 2));

	fclose(fp);
	flock(fileno(fp), LOCK_UN);

	return puerto;
}

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int validar_cuenta(char * cuenta){
	if( (cuenta == NULL) || ( strlen(cuenta) > max_digitos_cta) )
		return 0;
	return 1;
}

int es_nro(char * nro){

	int i=0;
	while(i < strlen(nro)){

		if( (!isdigit(nro[i]) )  && (nro[i] != '.'))
				return 0;
		i++;
	}
	return 1;
}

int validar_monto(char * monto){
	if((strlen(monto) < max_digitos_monto) && (es_nro(monto)))
		return 1;
	return 0;
}

char * enviar_mensaje(char * mensaje){

    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    int tam_buffer = 256;


    portno = obtener_puerto();

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR abriendo el puerto\n");

   server = gethostbyname(obtener_servidor());

    if (server == NULL) {
        fprintf(stderr,"ERROR, el servidor indicado no existe\n");
        exit(1);
    }

    memset((char *) &serv_addr,'\0', sizeof(serv_addr));
   // bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
        error("ERROR conectando con el servidor");

    n = write(sockfd,mensaje,strlen(mensaje)+1);
    if (n < 0)
         error("ERROR escribiendo al socket");

    char * buffer;
    buffer = (char*)calloc(tam_buffer, sizeof(char));

    memset(buffer, '\0', tam_buffer-1);
    n = read(sockfd,buffer,tam_buffer-1);
    if (n < 0)
         error("ERROR leyendo la respuesta");

    close(sockfd);
    return buffer;

}


char * depositar(char * nro_cuenta, char * monto){

	if(!validar_cuenta(nro_cuenta))
		return "el numero de cuenta es invalido";
	if(!validar_monto(monto))
		return "el monto es inválido";

	char msj[tam_msj];
	memset(msj, '\0', tam_msj);

	strcat(msj,nro_cuenta);
	strcat(msj,"| |D|");
	strcat(msj, monto);

	return enviar_mensaje(msj);
}

char * extraer(char * nro_cuenta, char * monto){

	if(!validar_cuenta(nro_cuenta))
		return "el numero de cuenta es invalido";
	if(!validar_monto(monto))
		return "el monto es inválido";


	char msj[tam_msj];
	memset(msj, '\0', tam_msj);

	strcat(msj,nro_cuenta);
	strcat(msj,"| |E|");
	strcat(msj,monto);

	return enviar_mensaje(msj);

}

char * consultar_saldo(char * nro_cuenta){

	if(!validar_cuenta(nro_cuenta))
		return "el numero de cuenta es invalido";

	char msj[tam_msj];
	memset(msj, '\0', tam_msj);

	strcat(msj,nro_cuenta);
	strcat(msj,"| |S| |");

	return enviar_mensaje(msj);
}

char * transferir(char * cta_origen, char * cta_destino, char * monto){

	if(!validar_cuenta(cta_origen) || !validar_cuenta(cta_destino))
		return "la cuenta ingresada es inválida";

	char msj[tam_msj];
	memset(msj, '\0', tam_msj);

	strcat(msj,cta_origen);
	strcat(msj,"|");
	strcat(msj,cta_destino);
	strcat(msj,"|T|");
	strcat(msj,monto);

	return enviar_mensaje(msj);
}
